#include "CollisionDetector.h"


CollisionDetector::CollisionDetector(void)
{
}


CollisionDetector::~CollisionDetector(void)
{
}

void CollisionDetector::collisionDetect(Shape *ps, list<Shape*> &l1) {
	if(ps->name.compare("RECT") == 0) {	//ps is a rect
		MRect *ps1 = (MRect *) ps;
		for(list<Shape*>::iterator it = l1.begin(); it!= l1.end(); it++) {
			if((*it)->name.compare("RECT") == 0) {	//its a rect
				MRect *ps2 = (MRect *) (*it);
				if(ps1->p2.first<=ps2->p1.first || ps1->p1.first >= ps2->p2.first) 
					continue;
				if(2*abs(ps2->p1.second- ps1->p1.second) <= (ps1->h+ps2->h)) {	//collision happen
					//move object up 
					float offset = ps2->p2.second - ps1->p1.second;
					ps1->p1.second += offset;
					ps1->p2.second += offset;
					ps1->speed = 0;
					ps1->bStop = true;
					l1.remove(*it);
					//break;
				}
			}
			else if((*it)->name.compare("CIRCLE") == 0) {	//its a circle
				MCircle *ps2 = (MCircle*)(*it);
				if((ps1->p1.first >= ps2->x+ps2->r) || (ps1->p2.first <= ps2->x-ps2->r) )
					continue;
				if(ps1->p1.first >= ps2->x && ps1->p1.first <= (ps2->x+ps2->r)) {	//rect on right side of circle
					if(sqrt(pow(ps1->p1.first - ps2->x,2) + pow(ps1->p1.second - ps2->y,2)) <= ps2->r ||
						(ps1->p1.second<=ps2->y)) {	//collision
							float newy = sqrt(pow(ps2->r,2) - pow(ps1->p1.first-ps2->x,2)) + ps2->y;
							ps1->p2.second += newy - ps1->p1.second;
							ps1->p1.second = newy;
							ps1->speed = 0;
							ps1->bStop = true;
							//l1.remove(*it);
							//break;
					}
				}
				else if(ps1->p2.first >= (ps2->x - ps2->r) && ps1->p2.first <= ps2->x) {	//rect on left side of circle
					if(sqrt(pow(ps1->p2.first- ps2->x,2) + pow(ps1->p1.second - ps2->y,2)) <= ps2->r ||
						(ps1->p1.second<=ps2->y)) {	//collision
							float newy = sqrt(pow(ps2->r,2) - pow(ps1->p2.first-ps2->x,2)) + ps2->y;
							float offset = newy - ps1->p1.second;
							ps1->p1.second += offset;
							ps1->p2.second += offset;
							ps1->speed = 0;
							ps1->bStop = true;
							//l1.remove(*it);
							//break;
					}
				}
				else {
					if(ps1->p1.second <= (ps2->y+ps2->r)) {	//collision
						ps1->p2.second += (ps2->y+ps2->r)-ps1->p1.second;
						ps1->p1.second = (ps2->y+ps2->r);
						ps1->speed = 0;
						ps1->bStop = true;
					}
				}
			}
		}
	} else if(ps->name.compare("CIRCLE") == 0) {	//ps is a circle
		MCircle *ps2 = (MCircle *) ps;
		for(list<Shape*>::iterator it = l1.begin(); it!= l1.end(); it++) {
			if((*it)->name.compare("CIRCLE") == 0) {	//object is an circle
				MCircle *ps1 = (MCircle *) (*it);
				if((pow(ps1->x-ps2->x,2)+pow(ps1->y-ps2->y,2)) <= pow(ps1->r+ps2->r,2)) {	//collision
					float newy = sqrt(pow((ps1->r+ps2->r),2)-pow(ps1->x-ps2->x,2)) + ps1->y;
					ps2->shift(0,newy-ps2->y);
					ps2->bStop = true;
					ps2->speed = 0;
					//break;
				}
			}
			else if((*it)->name.compare("RECT") == 0) {
				MRect *ps1 = (MRect *) (*it);
				if((ps2->x+ps2->r) <= ps1->p1.first || (ps2->x-ps2->r) >= ps1->p2.first)
					continue;
				if(ps2->x >= ps1->p1.first && ps2->x <= ps1->p2.first) {	//the lowest point of circle will touch the rect
					if(ps2->y-ps2->r < ps1->p2.second) {	//collision
						ps1->shift(0,ps2->r+ps1->p2.second-ps2->y);
						ps2->bStop = true;
						ps2->speed = 0;
					}
				}
			}
		}
	}
}


void CollisionDetector::collisionDetect(Shape *ps, list<Shape*> *l1) {
	if(ps->name.compare("RECT") == 0) {	//ps is a rect
		MRect *ps1 = (MRect *) ps;
		for(int i = (int)(ps1->p1.first*10); i <= (int)(ps1->p2.first*10);i++) {
			if(l1[i].empty()) 
				continue;
			for(list<Shape*>::iterator it = l1[i].begin(); it!= l1[i].end(); it++) {
				if((*it)->name.compare("RECT") == 0) {	//its a rect
					MRect *ps2 = (MRect *) (*it);
					if(ps1->p2.first<=ps2->p1.first || ps1->p1.first >= ps2->p2.first) 
						continue;
					if(2*abs(ps2->p1.second- ps1->p1.second) <= (ps1->h+ps2->h)) {	//collision happen
						//move object up 
						float offset = ps2->p2.second - ps1->p1.second;
						ps1->p1.second += offset;
						ps1->p2.second += offset;
						ps1->speed = 0;
						ps1->bStop = true;
					}
				}
				else if((*it)->name.compare("CIRCLE") == 0) {	//its a circle
					MCircle *ps2 = (MCircle*)(*it);
					if((ps1->p1.first >= ps2->x+ps2->r) || (ps1->p2.first <= ps2->x-ps2->r) )
						continue;
					if(ps1->p1.first >= ps2->x && ps1->p1.first <= (ps2->x+ps2->r)) {	//rect on right side of circle
						if(sqrt(pow(ps1->p1.first - ps2->x,2) + pow(ps1->p1.second - ps2->y,2)) <= ps2->r ||
							(ps1->p1.second<=ps2->y)) {	//collision
								float newy = sqrt(pow(ps2->r,2) - pow(ps1->p1.first-ps2->x,2)) + ps2->y;
								ps1->p2.second += newy - ps1->p1.second;
								ps1->p1.second = newy;
								ps1->speed = 0;
								ps1->bStop = true;
						}
					}
					else if(ps1->p2.first >= (ps2->x - ps2->r) && ps1->p2.first <= ps2->x) {	//rect on left side of circle
						if(sqrt(pow(ps1->p2.first- ps2->x,2) + pow(ps1->p1.second - ps2->y,2)) <= ps2->r ||
							(ps1->p1.second<=ps2->y)) {	//collision
								float newy = sqrt(pow(ps2->r,2) - pow(ps1->p2.first-ps2->x,2)) + ps2->y;
								float offset = newy - ps1->p1.second;
								ps1->p1.second += offset;
								ps1->p2.second += offset;
								ps1->speed = 0;
								ps1->bStop = true;
						}
					}
					else {
						if(ps1->p1.second <= (ps2->y+ps2->r)) {	//collision
							ps1->p2.second += (ps2->y+ps2->r)-ps1->p1.second;
							ps1->p1.second = (ps2->y+ps2->r);
							ps1->speed = 0;
							ps1->bStop = true;
						}
					}
				}
			}
		} 
	}
	else if(ps->name.compare("CIRCLE") == 0) {	//ps is a circle
		MCircle *ps2 = (MCircle *) ps;
		for(int i = (int)((ps2->x-ps2->r)*10); i <= (int)(int)((ps2->x+ps2->r)*10);i++) {
			if(l1[i].empty()) 
				continue;
			for(list<Shape*>::iterator it = l1[i].begin(); it!= l1[i].end(); it++) {
				if((*it)->name.compare("CIRCLE") == 0) {	//object is an circle
					MCircle *ps1 = (MCircle *) (*it);
					if((pow(ps1->x-ps2->x,2)+pow(ps1->y-ps2->y,2)) <= pow(ps1->r+ps2->r,2)) {	//collision
						float newy = sqrt(pow((ps1->r+ps2->r),2)-pow(ps1->x-ps2->x,2)) + ps1->y;
						ps2->shift(0,newy-ps2->y);
						ps2->bStop = true;
						ps2->speed = 0;
						//break;
					}
				}
				else if((*it)->name.compare("RECT") == 0) {
					MRect *ps1 = (MRect *) (*it);
					if((ps2->x+ps2->r) <= ps1->p1.first || (ps2->x-ps2->r) >= ps1->p2.first)
						continue;
					if(ps2->x >= ps1->p1.first && ps2->x <= ps1->p2.first) {	//the lowest point of circle will touch the rect
						if(ps2->y-ps2->r < ps1->p2.second) {	//collision
							ps1->shift(0,ps2->r+ps1->p2.second-ps2->y);
							ps2->bStop = true;
							ps2->speed = 0;
						}
					}
					else if(ps2->x < ps1->p1.first) {	//ball on left side of rect
						float lowercutpoint_y = (ps2->y-sqrt(pow(ps2->r,2) - pow(ps1->p1.first-ps2->x,2)));
						if( lowercutpoint_y < ps1->p2.second) {	//collison
							ps1->shift(0,ps1->p2.second - lowercutpoint_y);
							ps2->bStop = true;
							ps2->speed = 0;
						}
					}
					else if(ps2->x > ps1->p2.first) {	//ball on right side of rect
						float lowercutpoint_y = (ps2->y-sqrt(pow(ps2->r,2) - pow(ps1->p2.first-ps2->x,2)));
						if( lowercutpoint_y < ps1->p2.second) {	//collison
							ps1->shift(0,ps1->p2.second - lowercutpoint_y);
							ps2->bStop = true;
							ps2->speed = 0;
						}
					}
				}
			}
		}
	}
}
